package com.tanhan.mindapp.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tanhan.mindapp.dao.SysMenu;
import com.tanhan.mindapp.dao.SysRole;
import com.tanhan.mindapp.dao.SysRoleDTO.SysRoleQueryDTO;
import com.tanhan.mindapp.dao.SysRoleMenu;
import com.tanhan.mindapp.dao.SysUserRole;
import com.tanhan.mindapp.exception.AppException;
import com.tanhan.mindapp.mapper.SysRoleMapper;
import com.tanhan.mindapp.service.SysMenuService;
import com.tanhan.mindapp.service.SysRoleMenuService;
import com.tanhan.mindapp.service.SysRoleService;
import com.tanhan.mindapp.service.SysUserRoleService;
import com.tanhan.mindapp.utils.PageUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole> implements SysRoleService {
    @Autowired
    @Lazy
    private SysUserRoleService sysUserRoleService;

    @Autowired
    @Lazy
    private SysRoleMenuService sysRoleMenuService;
    @Autowired
    @Lazy
    private SysMenuService sysMenuService;

    /**
     * 删除角色（单个）
     *
     * @param roleId 角色ID
     * @return 是否删除成功
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteRole(Long roleId) {
        // 检查是否有用户使用该角色
        if (this.isRoleInUse(roleId)) {
            throw new AppException(9999, "角色正在被用户使用，无法删除");
        }

        // 执行删除操作
        return this.removeById(roleId);
    }

    /**
     * 批量删除角色
     *
     * @param roleIds 角色ID列表
     * @return 是否删除成功
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteBatchRoles(List<Long> roleIds) {
        // 检查每个角色是否被使用
        for (Long roleId : roleIds) {
            if (this.isRoleInUse(roleId)) {
                SysRole role = this.getById(roleId);
                throw new AppException(9999, "角色[" + (role != null ? role.getRoleName() : roleId) + "]正在被用户使用，无法删除");
            }
        }

        // 执行批量删除操作
        return this.removeByIds(roleIds);
    }

    /**
     * 检查角色是否被用户使用
     *
     * @param roleId 角色ID
     * @return 是否在使用中
     */
    @Override
    public boolean isRoleInUse(Long roleId) {
        QueryWrapper<SysUserRole> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("role_id", roleId);
        return sysUserRoleService.count(queryWrapper) > 0;
    }

    /**
     * 使用通用分页方法实现分页查询
     *
     * @param sysRoleQueryDTO 查询条件
     * @return 分页结果
     */
    @Override
    public IPage<SysRole> selectRolePage(SysRoleQueryDTO sysRoleQueryDTO) {
        QueryWrapper<SysRole> queryWrapper = new QueryWrapper<>();

        // 添加自定义条件查询
        if (sysRoleQueryDTO.getRoleName() != null && !sysRoleQueryDTO.getRoleName().isEmpty()) {
            queryWrapper.like("role_name", sysRoleQueryDTO.getRoleName());
        }
        if (sysRoleQueryDTO.getRoleCode() != null && !sysRoleQueryDTO.getRoleCode().isEmpty()) {
            queryWrapper.like("role_code", sysRoleQueryDTO.getRoleCode());
        }
        if (sysRoleQueryDTO.getStatus() != null && !sysRoleQueryDTO.getStatus().isEmpty()) {
            queryWrapper.eq("status", sysRoleQueryDTO.getStatus());
        }

        // 使用 PageUtils 进行分页（需要修改 PageUtils 添加相应重载方法）
        return PageUtils.pageQuery(this, sysRoleQueryDTO, queryWrapper);
    }

    /**
     * 为角色分配菜单权限
     *
     * @param roleId  角色ID
     * @param menuIds 菜单ID列表
     * @return 是否分配成功
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean assignMenuPermissions(String roleId, List<String> menuIds) {
        // 检查角色是否存在
        SysRole role = this.getById(roleId);
        if (role == null) {
            throw new AppException(9999, "角色不存在");
        }

        // 先删除该角色原有的菜单权限关联
        QueryWrapper<SysRoleMenu> deleteWrapper = new QueryWrapper<>();
        deleteWrapper.eq("role_id", roleId);
        sysRoleMenuService.remove(deleteWrapper);

        // 批量插入新的角色菜单权限关联
        if (menuIds != null && !menuIds.isEmpty()) {
            List<SysRoleMenu> roleMenuList = menuIds.stream()
                    .map(menuId -> {
                        SysRoleMenu roleMenu = new SysRoleMenu();
                        roleMenu.setRoleId(roleId);
                        roleMenu.setMenuId(menuId);
                        return roleMenu;
                    })
                    .collect(Collectors.toList());

            return sysRoleMenuService.saveBatch(roleMenuList);
        }

        return true;
    }

    /**
     * 获取角色的菜单权限
     *
     * @param roleId 角色ID
     * @return 菜单ID列表
     */
    @Override
    public List<String> getMenuPermissions(String roleId) {
        // 检查角色是否存在
        SysRole role = this.getById(roleId);
        if (role == null) {
            throw new AppException(9999, "角色不存在");
        }

        // 查询该角色关联的菜单权限
        QueryWrapper<SysRoleMenu> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("role_id", roleId);

        List<SysRoleMenu> roleMenus = sysRoleMenuService.list(queryWrapper);

        // 提取菜单ID列表
        return roleMenus.stream()
                .map(SysRoleMenu::getMenuId)
                .collect(Collectors.toList());
    }

    /**
     * 获取角色的菜单列表
     *
     * @param roleId 角色ID
     * @return 菜单列表
     */
    @Override
    public List<SysMenu> getMenuList(String roleId) {
        // 检查角色是否存在
        SysRole role = this.getById(roleId);
        if (role == null) {
            throw new AppException(9999, "角色不存在");
        }

        // 查询该角色关联的菜单权限
        QueryWrapper<SysRoleMenu> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("role_id", roleId);

        List<SysRoleMenu> roleMenus = sysRoleMenuService.list(queryWrapper);

        // 提取菜单ID列表
        List<String> menuIds = roleMenus.stream()
                .map(SysRoleMenu::getMenuId)
                .collect(Collectors.toList());

        // 根据菜单ID查询完整的菜单信息
        if (menuIds.isEmpty()) {
            return new ArrayList<>();
        }

        QueryWrapper<SysMenu> menuQueryWrapper = new QueryWrapper<>();
        menuQueryWrapper.in("id", menuIds);
        return sysMenuService.list(menuQueryWrapper);
    }

}
